package agent

import (
	"fmt"
	"strings"

	cfg "openmanus/config"
	"openmanus/tool"
)

// 添加了MCP支持的Manus
type Manus struct {
	*ToolCallAgent
}

func NewManusAgent(name string, llm *LLMClient, mcpConfig *cfg.MCPSettings) *Manus {
	// 创建工具集合
	toolCollection := tool.NewToolCollection()

	// 注册基础工具
	toolCollection.AddTool(tool.NewTerminate())
	toolCollection.AddTool(tool.NewAskHuman())
	toolCollection.AddTool(tool.NewFileOperatorsTool())
	toolCollection.AddTool(tool.NewWebSearch())

	manus := &Manus{ToolCallAgent: NewToolCallAgent(name, llm)}
	manus.AvailableTools = toolCollection
	manus.Description = "A versatile agent that can solve various tasks using multiple tools including MCP-based tools"

	manus.SystemPrompt = `
你是OpenManus，一个全能的人工智能助手，旨在解决用户提出的任何任务。
你拥有多种工具，可以随时调用以高效完成复杂请求。
无论是编程、信息检索、文件处理还是网页浏览，你都能应对自如。
请仔细分析用户需求，选择合适的工具并执行。
如果任务需要多个步骤，请一步一步来，确保每个步骤都正确执行。
`
	toolList := toolCollection.GetTools()
	toolDescs := make([]string, 0, len(toolList))
	for _, t := range toolList {
		toolDescs = append(toolDescs, fmt.Sprintf("- %s: %s", t.Name(), t.Description()))
	}
	NextStepPrompt := `
你拥有访问模型上下文协议（MCP）服务器权限，可以使用MCP服务器提供的工具来完成任务。
MCP服务器会动态显示可用工具，建议您先查看可用工具。

使用MCP工具时：
1.根据任务需求选择合适的工具
2.根据工具要求提供格式正确的参数
3.观察结果并据此决定下一步行动
4.工具在运行过程中可能会发生变化——可能出现新的工具，或现有工具消失

请遵循以下指南：
-调用工具时需使用其架构文件中定义的有效参数
-优雅地处理错误，通过理解问题所在并尝试使用更正的参数重试
-对于多媒体回复（例如图片），您将收到内容的描述
-使用最合适的工具，逐步完成用户请求
-若需按顺序调用多个工具，请一次调用一个并等待结果

调用工具触发条件：
请在回答前先判断：是否需要调用上述工具才能给出准确答案？若符合以下情况，**必须调用工具**，禁止直接回答：
- 情况1：回答依赖“实时性信息”（如当前天气、实时股价、最新汇率、今日新闻），你无法凭内置知识获取（内置知识截止到【当前时间，如2025年10月】，无法更新实时数据）。
- 情况2：回答依赖“精准计算/查询数据”（如某城市历史最高温、某股票近3天涨跌幅），你无法凭记忆精准回答。
- 情况3：用户明确要求“用工具查询”（如“帮我查一下上海现在的天气”“调用股票工具看腾讯控股的行情”）。

若符合以下情况，**无需调用工具**，可直接回答：
- 情况1：问题不涉及实时/精准数据（如“天气查询工具能查什么信息？”“股票代码由几位数字组成？”）。
- 情况2：你已通过前一次工具调用获取了所需数据（如用户追问“刚才查的北京天气，湿度是多少？”，无需再次调用）。

参数缺失处理：
若用户的问题中缺少工具所需的**必填参数**（如用户只说“查天气”，未提城市），请先向用户追问获取关键信息，**不允许猜测参数**：
- 正确追问：“你需要查询哪个城市的天气？请提供城市全称（如“北京市”）。”
- 错误做法：直接调用工具，猜测参数为“北京市”。

您还可以使用以下系统内置工具：
%s

根据用户需求，主动选择最合适的工具或工具组合。对于复杂任务，可以将问题分解，逐步使用不同的工具来解决。
请务必向用户清晰说明您的推理过程和操作步骤。
使用每种工具后，清晰地解释执行结果，并建议下一步。
在整个互动过程中始终保持一种乐于助人、信息丰富的语气。
如果您遇到任何限制或需要更多细节，请在结束之前清楚地告知用户并调用"Terminate"工具。
`
	manus.NextStepPrompt = fmt.Sprintf(NextStepPrompt, strings.Join(toolDescs, "\n"))

	// 添加MCP工具
	manus.Initialize_mcp_servers(mcpConfig)

	return manus
}

/*
connect_mcp_server(
        self,
        server_url: str,
        server_id: str = "",
        use_stdio: bool = False,
        stdio_args: List[str] = None,

        # Update available tools with only the new tools from this server
        new_tools = [
            tool for tool in self.mcp_clients.tools if tool.server_id == server_id
        ]
        self.available_tools.add_tools(*new_tools)

disconnect_mcp_server(self, server_id: str = "") -> None:
        """Disconnect from an MCP server and remove its tools."""
        await self.mcp_clients.disconnect(server_id)
        if server_id:
            self.connected_servers.pop(server_id, None)
        else:
            self.connected_servers.clear()

        # Rebuild available tools without the disconnected server's tools
        base_tools = [
            tool
            for tool in self.available_tools.tools
            if not isinstance(tool, MCPClientTool)
        ]
        self.available_tools = ToolCollection(*base_tools)
        self.available_tools.add_tools(*self.mcp_clients.tools)
*/
